package com.rkc.component;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradePagePayResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeWapPayResponse;
import com.rkc.config.AlipayConfiguration;
import com.rkc.config.PayUrlConfiguration;
import com.rkc.enums.BizCodeEnum;
import com.rkc.enums.ClientType;
import com.rkc.exception.BizException;
import com.rkc.vo.PayInfoVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

/**
 * @author `RKC`
 * @date 2022/3/6 14:41
 */
@Slf4j
@Component
public class AlipayStrategy implements PayStrategy {

    @Autowired
    private PayUrlConfiguration payUrlConfiguration;

    @Override
    public String unifiedOrder(PayInfoVO payInfoVO) {
        Map<String, String> content = new HashMap<>(10);
        //商户订单号,64个字符以内、可包含字母、数字、下划线；需保证在商户端不重复
        log.info("订单号:{}", payInfoVO.getOutTradeNo());
        content.put("out_trade_no", payInfoVO.getOutTradeNo());
        content.put("product_code", "FAST_INSTANT_TRADE_PAY");
        //订单总金额，单位为元，精确到小数点后两位
        content.put("total_amount", payInfoVO.getPayFee().toString());
        //商品标题/交易标题/订单标题/订单关键字等。 注意：不可使用特殊字符，如 /，=，&amp; 等。
        content.put("subject", payInfoVO.getTitle());
        //商品描述，可空
        content.put("body", payInfoVO.getDescription());
        //剩余支付的分钟
        double timeout = Math.floor(payInfoVO.getOrderPayTimeoutMills() / (1000 * 60d));
        //前端也需要判断订单是否要关闭了，如果快要到期了就不给进行二次支付
        if (timeout < 1) {
            throw new BizException(BizCodeEnum.PAY_ORDER_PAY_TIMEOUT);
        }
        // 该笔订单允许的最晚付款时间，逾期将关闭交易。取值范围：1m～15d。m-分钟，h-小时，d-天，1c-当天（1c-当天的情况下，无论交易何时创建，都在0点关闭）。 该参数数值不接受小数点， 如 1.5h，可转换为 90m。
        content.put("timeout_express", Double.valueOf(timeout).intValue() + "m");
        String clientType = payInfoVO.getClientType(), result = "";
        try {
            if (clientType.equalsIgnoreCase(ClientType.H5.name())) {
                //H5手机网页支付
                AlipayTradeWapPayRequest payRequest = new AlipayTradeWapPayRequest();
                payRequest.setBizContent(JSON.toJSONString(content));
                payRequest.setNotifyUrl(payUrlConfiguration.getAlipayCallbackUrl());
                payRequest.setReturnUrl(payUrlConfiguration.getAlipaySuccessReturnUrl());
                //得到执行后的响应
                AlipayTradeWapPayResponse payResponse = AlipayConfiguration.getInstance().pageExecute(payRequest);
                if (payResponse.isSuccess()) {
                    result = payResponse.getBody();
                } else {
                    log.error("支付宝构建H5表单失败：response={}，payInfo={}", payResponse, payInfoVO);
                }
            } else if (clientType.equalsIgnoreCase(ClientType.PC.name())) {
                //PC支付
                AlipayTradePagePayRequest payRequest = new AlipayTradePagePayRequest();
                payRequest.setBizContent(JSON.toJSONString(content));
                payRequest.setNotifyUrl(payUrlConfiguration.getAlipayCallbackUrl());
                payRequest.setReturnUrl(payUrlConfiguration.getAlipaySuccessReturnUrl());
                AlipayTradePagePayResponse payResponse = AlipayConfiguration.getInstance().pageExecute(payRequest);
                if (payResponse.isSuccess()) {
                    result = payResponse.getBody();
                } else {
                    log.error("支付宝构建PC表单失败：response={}，payInfo={}", payResponse, payInfoVO);
                }
            }
        } catch (AlipayApiException e) {
            log.error("支付宝支付出现异常：payInfo={}，异常={}", payInfoVO, e);
        }
        return result;
    }

    @Override
    public String queryPayState(PayInfoVO payInfoVO) {
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        //订单商户号，64位
        Map<String, String> args = new HashMap<>(1);
        args.put("out_trade_no", payInfoVO.getOutTradeNo());
        request.setBizContent(JSON.toJSONString(args));
        AlipayTradeQueryResponse response = null;
        try {
            response = AlipayConfiguration.getInstance().execute(request);
            log.info("支付宝订单查询响应：{}", response.getBody());
        } catch (AlipayApiException e) {
            log.error("支付宝订单查询异常：{}", e.toString());
        }
        if (response.isSuccess()) {
            log.info("支付宝订单状态查询成功：{}", payInfoVO);
            return response.getTradeStatus();
        }
        log.info("支付宝订单状态查询成功：{}", payInfoVO);
        return "";
    }
}
